#include "sincronizacion.h"

/*hilo sincronizacion.Falta hacer la llamada, cuando se detecta un nuevo disco*/
void generarThreadSincronizacion(t_infoDisco *disco){
	pthread_t hiloSincronizacion;
	if(pthread_create (&hiloSincronizacion, NULL, (void*)sincronizacion, (void *)disco)){
		printf("ERROR");
		logMessage(LOG_ERR,"No se pudo generar el hilo de sincronizacion");
	}
}

void *sincronizacion (t_infoDisco *disco){
	copiarEscriturasPendientes_disco(disco);
	copiarInformacionDisco(disco);
	return NULL;
}

void copiarEscriturasPendientes_disco(t_infoDisco *discoNuevo){

	t_infoDisco* discoSincronizado = seleccionarDiscoActivo(tablaDisco);

    int cant=0;
    t_queue *colaPendienteDisco = (t_queue*)discoSincronizado->colaPendientesPetDisco;

    while (cant <= collection_list_size(colaPendienteDisco)){

        t_peticion *peticion = (t_peticion*)collection_list_get(colaPendienteDisco,cant);

        if(peticion->tipoPeticion == Escritura){

            collection_queue_push(discoNuevo->colaPendientesPetDisco,peticion);
            collection_queue_push(discoNuevo->colaSectoresCopiados,peticion);
        }
        cant++;
    }
}

t_infoDisco *seleccionarDiscoActivo(t_list *tablaDisco){

    int cant=0;
    t_infoDisco *disco = (t_infoDisco*)collection_list_get(tablaDisco,cant);

    while (cant <= collection_list_size(tablaDisco) && disco->sectoresCopiados == 0){

        cant++;
        disco = (t_infoDisco*)collection_list_get(tablaDisco,cant);
    }

    return disco;
}

void copiarInformacionDisco(t_list *tablaDisco){

    int sector = 0;
    int indexDisco = 0;

    while (indexDisco <= collection_list_size(tablaDisco)){

		t_infoDisco *disco = (t_infoDisco*)collection_list_get(tablaDisco,indexDisco);

		while (sector <= (disco->sectoresCopiados)){
			t_peticion *peticion = peticionDeLectura(sector);
			encolarPeticiones(peticion, peticiones);
		}

		sector++;
		indexDisco++;
    }

}

t_peticion *peticionDeLectura(int sector){

	t_peticion *peticion = inicializarPeticion();

	peticion->tipoPeticion = LecturaSincro;
	peticion->length = 0;
	peticion->sPayload->nSector = sector;
	peticion->flagSincro = 1;

	return peticion;
}

t_peticion *generarPeticionFinSincronizacion(){

	t_peticion *peticion = inicializarPeticion();

	peticion->tipoPeticion = FinSincro;
	peticion->length = 0;
	peticion->sPayload->nSector = 0;
	peticion->flagSincro = 1;

	return peticion;
}

void generarPeticionDeEscritura(t_peticion *peticion){
	int	primerDisco = 0;
	t_infoDisco *discoD = (t_infoDisco*)collection_list_get(tablaDisco,primerDisco);
	t_peticion *peticionSincro = peticionDeEscritura(peticion);
	encolarPeticiones(peticionSincro, peticiones);
	if (peticion->sPayload->nSector == discoD-> sectoresCopiados){
		t_peticion *finPeticion = generarPeticionFinSincronizacion();
		encolarPeticiones(finPeticion, peticiones);
	}

}

t_peticion *peticionDeEscritura(t_peticion *peticion){
	t_peticion* peticionSincro = inicializarDistribucion();

	peticionSincro->tipoPeticion = EscrituraSincro;
	peticionSincro->length = 0;
	peticionSincro->sPayload->nSector = peticion->sPayload->nSector;
	peticionSincro->sPayload->data = (char*)malloc(sizeof(512));
	memcpy(peticionSincro->sPayload->data,(peticion->sPayload->data),strlen(peticion->sPayload->data)+1);
	peticionSincro->flagSincro = 1;

	return peticionSincro;
}

void validarFinSincro(t_infoDisco *disco, time_t tiempoInicio){
	t_infoDisco * discoD = getDiscoD();
	if (disco->sectoresCopiados == discoD->sectoresCopiados){
		time_t tiempoFinal;
		tiempoFinal = time(NULL);
		tiempoSincronizacion ((tiempoFinal - tiempoInicio), disco->idDisco);
		disco->estado = Activo;
		collection_queue_destroy(disco->colaSectoresCopiados, (void *) destruirPeticion);
	}
}

void tiempoSincronizacion (time_t Time, int id){
	struct tm *finalTime;
	char time[9];

	finalTime = localtime(&Time);

	printf("El tiempo de sincronizacion del disco: %s\n fue de: %s\n",id, strftime(time, 9, "%H%M%S", finalTime));

}

t_infoDisco * getDiscoD (){
	t_list* list = getListaInfoDisco();

	int	primerDisco = 0;
	t_infoDisco *discoD = collection_list_get(list,primerDisco);

	while ( primerDisco < collection_list_size(list)){
		if (discoD->soyDiscoD == 1){
			break;
		}else{
			primerDisco++;
			discoD = collection_list_get(list,primerDisco);
		}
	}

	return discoD;

}
